feat(storage): sign Azure layer-file uploads with a SAS - #3634
michalsuba-e2b wants to merge 3 commits into
Conversation
…load headers
Azure's Put Blob requires the request header "x-ms-blob-type: BlockBlob". A SAS can
only pin response headers, so no signed URL alone can satisfy it and the provider
refused to issue one at all — every template build with a COPY instruction failed on
Azure at the get-signed-URL step.
UploadSignedURL now returns {URL, Headers} instead of a bare URL, and the header
travels with the URL through the gRPC and public API responses for the upload client
to apply. Azure mints a create+write blob SAS with whichever credential the provider
already authenticated with: a user delegation key for a token credential (the managed
identity path), or the shared key when one is configured. A SAS-only connection string
can sign neither and now says so at construction and at the call. GCS, S3 and the
filesystem provider return nil headers and byte-identical URLs.
The proto and OpenAPI additions are additive — url stays optional, and a client that
ignores the new field parses the response unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
CI attribution, for the reviewer (current run, after the main merge — 38 pass / 4 fail): The only failures are Everything else is green, including the two flakes from the previous run: |
|
Live-environment validation on an Azure BYOC env (miso9), dev |
…rance' into feat/azure-signed-upload-headers # Conflicts: # packages/api/internal/api/api.gen.go
Standing review rule: a comment states one constraint on one line; reasoning lives here, not at the fix site. No behavior change; tests unchanged and green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Moved to belt (source of truth): e2b-dev/belt#3308 (stacked on e2b-dev/belt#3307). Same diff, paths remapped; live miso9 evidence and review threads referenced from there. Closing. |
… link (#1870) The API now returns request headers with a file-upload link (e2b-dev/belt#3308, moved from e2b-dev/runtime#3634 — Azure `Put Blob` needs `x-ms-blob-type`, which its SAS cannot carry); both SDKs apply them on the upload PUT. Header-less providers (S3/GCS/fs) get byte-identical requests, so nothing changes off Azure. - JS: `getFileUploadLink` returns `headers`; `putFileStream` merges them under our own `Content-Length`, stripping any API-sent Content-Length case-insensitively. - Python sync + async: `upload_file` takes keyword-only `headers`, merged the same way (sync mirrored to async per review). - Tests: header pass-through, no-headers guard, and Content-Length-stays-ours (lowercase spelling to pin case-insensitivity), in JS and both Python variants; live suites (GCS production path) green. - Validated e2e at head against an Azure BYOC env (miso9) through staging api + edge: multi-COPY build green with uploads landing (cache miss) and a zero-upload green rerun (cache hit); earlier direct probes: headers applied → 201, stripped → `MissingRequiredHeader`. - `spec/runtime-ref` pins runtime `main` (`756512ca8`), which carries the merged contract (e2b-dev/belt#3308). Changesets: one patch per SDK. Sponsor: @michalsuba-e2b 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Azure template builds fail on every
COPY:Put Blobrequires thex-ms-blob-typerequest header, which a SAS cannot carry and the upload client never sent. The Azure provider now signs a real upload SAS, and the response carries the request headers the client must send.UploadSignedURLreturnsUploadURL{URL, Headers}; GCS/S3/fs return no headers — responses byte-identical, guard-tested (MinIO live for S3).InitLayerFileUploadResponse.uploadHeaders = 3+ OpenAPIheaders, both additive; the api handler passes them through only when non-empty.MissingRequiredHeader, with header → 201; SDK counterpart fix(sdk): apply the upload headers the API returns with a file upload link E2B#1870.Stacked on #3633. CI note:
validate-openapiis red onmainfor all three specs; this branch's +5 spec lines change nothing in its output.Sponsor: @michalsuba-e2b
🤖 Generated with Claude Code